/** 本机字节顺序转网络字节顺序
 * @file intconv.hpp
 * @author Kiven Lee
 * @version 1.0
 * @date 2021-09-14
 *
 * @copyright Kivensoft (c) 2018 - 2021
 *
 */

#pragma once

#include <cstdint>

namespace klib {
    namespace net {
        static inline uint16_t n2h(uint16_t a) {
            #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
                return (a >> 8) | (a << 8);
            #else
                return a;
            #endif
        }

        static inline uint32_t n2h(uint32_t a) {
            #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
                return (a >> 24) | (a >> 8 & 0xFF00) | (a << 8 & 0xFF0000 ) | (a << 24);
            #else
                return a;
            #endif
        }

        static inline uint64_t n2h(uint64_t a) {
            #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
                return (a >> 56) | (a >> 40 & 0xFF00) | (a >> 24 & 0xFF0000)
                    | (a >> 8 & 0xFF000000) | (a << 8 & 0xFF00000000) |
                    (a << 24 & 0xFF0000000000) | (a << 40 & 0xFF000000000000) | (a << 56);
            #else
                return a;
            #endif
        }


        static inline int16_t n2h(int16_t a) { return n2h((uint16_t)a); }

        static inline int32_t n2h(int32_t a) { return n2h((uint32_t)a); }

        static inline int64_t n2h(int64_t a) { return n2h((uint64_t)a); }

        static inline float n2h(float a) {
            #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
                union U { float a; uint8_t b[4]; } r;
                uint8_t *fb = ((U*)&a)->b + 3, *rb = r.b;
                *rb++ = *fb--; *rb++ = *fb--;
                *rb++ = *fb--; *rb++ = *fb--;
                return r.a;
            #else
                return a;
            #endif
        }

        static inline double n2h(double a) {
            #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
                union U { double a; uint8_t b[8]; } r;
                uint8_t *fb = ((U*)&a)->b + 7, *rb = r.b;
                *rb++ = *fb--; *rb++ = *fb--;
                *rb++ = *fb--; *rb++ = *fb--;
                *rb++ = *fb--; *rb++ = *fb--;
                *rb++ = *fb--; *rb++ = *fb--;
            return r.a;
            #else
                return a;
            #endif
        }

        static inline uint16_t h2n(uint16_t a) { return n2h(a); }
        static inline uint32_t h2n(uint32_t a) { return n2h(a); }
        static inline uint64_t h2n(uint64_t a) { return n2h(a); }
        static inline int16_t  h2n(int16_t a)  { return n2h(a); }
        static inline int32_t  h2n(int32_t a)  { return n2h(a); }
        static inline int64_t  h2n(int64_t a)  { return n2h(a); }
        static inline float    h2n(float a)    { return n2h(a); }
        static inline double   h2n(double a)   { return n2h(a); }

    } // namespace net


} // namespace kliib
